﻿using System;
using BotDetector.Core.Model;

namespace BotDetector.Core.Detector
{
    public class KeyWordsAnalyzor : IAnalyzer
    {
        private BotLength typeOfLength;

        public KeyWordsAnalyzor(BotLength typeLength)
        {
            typeOfLength = typeLength;
        }
        public bool AnalyzeAfterKeyWords(ResultItemList resultItemList)
        {
            int nrOfBotResults = 0;
            int wordsNumber = DetectValueNeeded(4, 7, 15);
            int valueOfResultsNumber = DetectValueNeeded(4, 3, 2);
            nrOfBotResults = CountBotResults(resultItemList, nrOfBotResults, wordsNumber);
            if (nrOfBotResults >= valueOfResultsNumber)
            {
                return true;
            }
            return false;
        }

        private int CountBotResults(ResultItemList resultItemList, int nrOfBotResults, int wordsNumber)
        {
            foreach (var webResult in resultItemList)
            {
                string content;
                string[] keyWords;
                int nrOfKeyWordsFound = CountKeywordsFound(webResult, out content, out keyWords);
                if ((nrOfKeyWordsFound >= wordsNumber) &&
                    AnalyzeDistances(content, keyWords))
                {
                    nrOfBotResults++;
                }
            }
            return nrOfBotResults;
        }
        private static int CountKeywordsFound(ResultItem webResult, out string content, out string[] keyWords)
        {
            string[] separators = { ",", ".", "!", "?", ";", ":", " " };
            int nrOfKeyWordsFound = 0;
            content = webResult.Description.Replace("\n", string.Empty);
            string[] words = content.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            keyWords = GetKeyWords(words);
            nrOfKeyWordsFound = CountNumberOfKeywordsFoundInResult(content, keyWords, nrOfKeyWordsFound);
            return nrOfKeyWordsFound;
        }

        private static int CountNumberOfKeywordsFoundInResult(string content, string[] keyWords, int nrOfKeyWordsFound)
        {
            foreach (var keyWord in keyWords)
            {
                if (!string.IsNullOrEmpty(keyWord)
                    && content.Contains(keyWord))
                {
                    nrOfKeyWordsFound++;
                }
            }
            return nrOfKeyWordsFound;
        }

        private static string[] GetKeyWords(string[] words)
        {
            string[] keyWords;
            keyWords = new string[100];
            int i = 0;
            foreach (string word in words)
            {
                if (word.Length > 3)
                {
                    keyWords[++i] = word;
                }
            }
            return keyWords;
        }
        private bool AnalyzeDistances(string content, string[] keyWords)
        {
            const string newLine = "\n";
            string[] separators = keyWords;
            content = content.Replace(newLine, string.Empty);
            string[] leftOverWords = content.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            int smallDistancesFound = CountSmallDistances(leftOverWords);
            if (smallDistancesFound / leftOverWords.Length > 0.3)
            {
                return true;
            }
            return false;
        }

        private static int CountSmallDistances(string[] leftOverWords)
        {
            int smallDistancesFound = 0;
            foreach (string word in leftOverWords)
            {
                if (word.Length < 10)
                {
                    smallDistancesFound++;
                }
            }
            return smallDistancesFound;
        }
        public int DetectValueNeeded(int shortValue, int mediumValue, int longValue)
        {
            if (typeOfLength == BotLength.Short)
            {
                return shortValue;
            }
            if (typeOfLength == BotLength.Medium)
            {
                return mediumValue;
            }
            return longValue;
        }
        public bool Analyze(ResultItemList resultItemList)
        {
            return AnalyzeAfterKeyWords(resultItemList);
        }
    }
}
